package com.cee.admin.common;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.cee.admin.common.utils.HttpServletUtils;
import com.cee.admin.log.util.OperateLogUtils;
import com.cee.common.annotations.OrderParam;
import com.cee.common.lang.ReflectUtils;
import com.cee.common.web.result.ResultHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.util.HtmlUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.beans.PropertyEditorSupport;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

import static com.cee.domain.constants.DomainConstants.OrderType.ASC;
import static com.cee.domain.constants.DomainConstants.OrderType.DESC;


/**
 * Controller 基类
 *
 * @author rxliuli by 2018/4/18 23:11
 */
public abstract class BaseController implements ResultHelper {
    /**
     * Controller 的日志记录实例
     */
    protected final Logger log = LoggerFactory.getLogger(getClass());


    /**
     * 初始化数据绑定
     *
     * @param binder 数据绑定器，用以处理 servlet 参数到 Bean 实体的绑定
     */
    @InitBinder
    public void initBinder(ServletRequestDataBinder binder) {
        /*
         * 防止 XSS 攻击
         */
        binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
            @Override
            public String getAsText() {
                Object value = getValue();
                return value != null ? value.toString() : "";
            }

            @Override
            public void setAsText(String text) {
                setValue(text == null ? null : HtmlUtils.htmlEscape(text));
            }
        });
        //这种方式只能兼容一种格式
//        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        dateFormat.setLenient(false);//是否严格解析时间 false则严格解析 true宽松解析
//        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
//        binder.registerCustomEditor(LocalDateTime.class, CUSTOM_LOCAL_DATE_TIME_EDITOR);
//        binder.registerCustomEditor(LocalDate.class, CUSTOM_LOCAL_DATE_EDITOR);
//        binder.registerCustomEditor(LocalTime.class, CUSTOM_LOCAL_TIME_EDITOR);
    }

    protected ServletOutputStream wrapDownloadResponse(String filename) throws IOException {
        HttpServletResponse httpServletResponse = HttpServletUtils.getResponse();
        try {
            httpServletResponse.setCharacterEncoding(StandardCharsets.UTF_8.name());
            httpServletResponse.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            httpServletResponse.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8.name()));
            httpServletResponse.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        } catch (UnsupportedEncodingException ignore) {
        }
        return httpServletResponse.getOutputStream();
    }

    protected ServletOutputStream setDownloadResponse(String filename) {
        try {
            return wrapDownloadResponse(filename);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 处理排序字段
     * @param obj
     */
    protected void handleOrder(Object obj) {
        Field[] fieldValues = ReflectUtils.getAnnotatedFields(obj.getClass(), OrderParam.class);
        boolean hasOrder = false;
        for (Field field: fieldValues) {
            if (!String.class.isAssignableFrom(field.getType())) {
                log.error("OrderParam注解并没有使用在String类型的字段上, class:{}, field:{}", obj.getClass().getName(), field.getName());
                continue;
            }
            String fieldValue = (String)ReflectUtils.getFieldValue(obj, field);
            if (hasOrder || StringUtils.isBlank(fieldValue)){
                ReflectUtils.setFieldValue(obj, field, null);
                continue;
            }
            ReflectUtils.setFieldValue(obj, field, ASC.getCode().equals(fieldValue.trim()) ? ASC.getValue() : DESC.getValue());
            hasOrder = true;
        }
    }



    protected void changeOperationLogName(String name) {
        OperateLogUtils.setLogPreprocessor(log->log.setName(name));
    }
}
